// 计时器
/*
	Like the real thing, you can start and stop a stopwatch,
	and you can find out the elapsed time the stopwatch has been running.
	After you stop a stopwatch, its getElapsedTime() method returns the elapsed time between the start and stop.

	Stopwatches are used primarily for timing animations.
*/
function Stopwatch(){

}

Stopwatch.prototype = {
	startTime: 0,
	running: false,
	elapsed: undefined,

	start: function(){
		this.startTime = +new Date();
		this.elapsedTime = undefined;
		this.running = true;
	},

	stop: function(){
		this.elapsed = (+new Date()) - this.startTime;
		this.running = false;
	},

	getElapsedTime: function(){
		if(this.running){
			return (+new Date()) - this.startTime;
		}else{
			return this.elapsed;
		}
	},

	isRunning: function(){
		return this.running;
	},

	reset: function(){
		this.elapsed = 0;
	}
};

/*............................................................................*/

// 动画计时器
function AnimationTimer(duration, timeWrap){
	this.duration = duration;
	this.timeWrap = timeWrap;
	this.stopwatch = new Stopwatch();
}

AnimationTimer.prototype = {
	start: function(){
		this.stopwatch.start();
	},

	stop: function(){
		this.stopwatch.stop();
	},

	getRealElapsedTime: function(){
		return this.stopwatch.getElapsedTime();
	},

	getElapsedTime: function(){
		var elapsedTime = this.stopwatch.getElapsedTime(),
			percentComplete = elapsedTime / this.duration;

		if(!this.stopwatch.running) return undefined;
		if(this.timeWrap == undefined) return elapsedTime;

		return elapsedTime * (this.timeWrap(percentComplete) / percentComplete);
	},

	isRunning: function(){
		return this.stopwatch.isRunning();
	},

	isOver: function(){
		return this.stopwatch.getElapsedTime() > this.duration;
	},

	reset: function(){
		return this.stopwatch.reset();
	}
};

// 时间扭曲函数

// 缓入
AnimationTimer.makeEaseIn = function(strength){
	return function(percentComplete){
		return Math.pow(percentComplete, strength * 2);
	};
};

// 缓出
AnimationTimer.makeEaseOut = function(strength){
	return function(percentComplete){
		return 1 - Math.pow(1 - percentComplete, strength * 2);
	};
};

// 缓入缓出
AnimationTimer.makeEaseInOut = function(){
	return function(percentComplete){
		return percentComplete - Math.sin(percentComplete * 2 * Math.PI) / (2 * Math.PI);
	};
};

// 匀速
AnimationTimer.makeLinear = function(){
	return function(percentComplete){
		return percentComplete;
	};
};

// 弹簧运动
AnimationTimer.makeElastic = function(passes){
	// passes = passes || DEFAULT_ELASTIC_PASSES;
	passes = passes || 3;
	return function(percentComplete){
		return ((1 - Math.cos(percentComplete * Math.PI * passes)) * (1 - percentComplete)) + percentComplete;
	};
};

// 弹跳运动
AnimationTimer.makeBounce = function(bounces){
	var fn = AnimationTimer.makeElastic(bounces);
	return function(percentComplete){
		percentComplete = fn(percentComplete);
		return percentComplete <= 1 ? percentComplete : 2 - percentComplete;
	};
};